(defmeth vista-loglinear-proto :current-model ()
  (let* ((terms (expand-hierarchy (list (iseq (length (send self :vars))))))
         (terms-included (select (send self :terms)  
                                 (send self :current-num-adjusted-model)))
         (terms-in-model (select terms 
                               (select terms-included
                                       (which (mapcar #'(lambda (ter)
                                                          (< ter (length terms)))	
                                                      terms-included )))))
                         )
    terms-in-model))

(defmeth vista-loglinear-proto :parametters-plot ()
  (let* (
         (object self)
         (num-lab (mapcar 'length (send self :level-labels)))
         (model (send (send self :curr-model) :set-model))
         (num-indicators (length (send object :label-current-indicators)))
         (num-elements-by-term (mapcar #'(lambda (m) (reduce '* (- (select num-lab m) 1))) model))
         (num-elements-by-term (if (> num-indicators 0) (combine num-elements-by-term (repeat '1 num-indicators))
                                       num-elements-by-term))
         (coef-estimates (combine (send (send self :curr-model) :coef-estimates)))
         (coef-errors (combine (send (send self :curr-model) :coef-standard-errors)))
         (z (cdr (/ coef-estimates coef-errors)))
         (num-var (iseq (length model)))
         (x (cdr (combine 1 (+ 2 (combine 
                                  (mapcar #'(lambda (v y) 
                                              (repeat v y)) 
                                          num-var num-elements-by-term))))))
         ; (pred-names (cdr (combine "Const" (send self :predictor-names))))
         ; (pred-names (cdr (combine "Const" (send object :parametter-interpretation))))
         (pred-names (send object :parametter-interpretation))
         (numerators (mapcar #'(lambda (pred) (first (combine pred)))
                             pred-names))
         (denominators (mapcar #'(lambda (pred) (second (combine pred)))
                               pred-names))
         (end-part (mapcar #'(lambda (pred) (third (combine pred)))
                           pred-names))
         (vlg self)
         (plot 
          (plot-points
           x
           ;z 
           (cdr (combine coef-estimates))
           :show nil
           :point-labels (send self :predictor-names) 
           :symbol 'x
           ))
         )
   ;dokey method for changing the order of the parameters and for not showing the fancy interpretation labels

    (send plot :add-slot 'print-interpretation-labels)
   
    (defmeth plot :do-key (char shift option)
      
      (when (and option (equal char '#\C-A))
            (send vlg :order-of-variables (combine (cdr (send vlg :order-of-variables)) 
                                                     (car (send vlg :order-of-variables)))))

       (when (and option (equal char '#\C-I))
              (if (equal (send self :slot-value 'print-interpretation-labels) t)
                  (send self :slot-value 'print-interpretation-labels 'nil)
             (send self :slot-value 'print-interpretation-labels 't))
              (print (send self :slot-value 'print-interpretation-labels)))
      (send self :redraw)
      )

    ;install menu for changing reference categories
    (setf reference-category-menu  
          (send menu-item-proto :new "Reference Categories..." 
                :action #'(lambda () 
                            (send object :reference-category-dialog 
                                  (send plot :spreadplot-object)))))

    ;new menu for saving as pdf

(setf ask-save-pdf  
          (send menu-item-proto :new "Save Plot As..." 
                :action #'(lambda () 
                            (send plot :ask-save-pdf))))
  
  (send plot :hotspot-menu-items (remove 'nil (combine (send plot :hotspot-menu-items) reference-category-menu ask-save-pdf)))
    
    (send plot :use-color t)
    (send plot :plot-buttons  :mouse-mode nil :new-x nil :new-y nil :free nil)
    (send plot :point-color (iseq (send plot :num-points)) 'blue)
    (send plot :delete-mouse-mode 'brushing)
  ; (send (send plot :menu) :delete-items (third (send (send plot :menu) :items)))
  ;  (send (send plot :menu) :delete-items (second (send (send plot :menu) :items)))
   ; (send (send plot :menu) :delete-items (second (send (send plot :menu) :items)))
    (send plot :x-axis t t 0)
    (send plot :y-axis t t (third (send plot :y-axis)))
    (send plot :mouse-mode 'selecting)
    (send plot :range '0 1 (+ 3 (last num-var)))
    (setf min-range (min (send plot :range '0)))
    (setf max-range (max (send plot :range '0)))
    (send plot :add-lines (list (list min-range max-range) 
                                (list 0 0)) :color 'orange :type 'dashed)
   #| (send plot :add-lines (list  (list min-range max-range) 
                                   (list 1.96 1.96)) :color 'orange :type 'dashed)
    (send plot :add-lines (list  (list min-range max-range) 
                                 (list -1.96 -1.96)) :color 'orange :type 'dashed)
    (defmeth plot :showing-labels (&optional arg)
      )
    (send plot :showing-labels t)|#
    (defmeth plot :print-var-labels ()
      (let* (
             (model (send (send object :curr-model) :set-model))
             (num-indicators (length (send object :label-current-indicators)))
             (num-var (iseq (+ num-indicators (length model))))
             (min-range (min (send self :range '1)))
             (max-range (max (send self :range '1)))
             ;(min-range 0)
             (positions (mapcar #'(lambda (var) (send self :real-to-canvas var min-range))
                                (cdr (combine 1 (+ 2 num-var)))))
             (terms (cdr (combine "Const" (send object :current-set-model))))
             (terms (if (send object :dependent-variable) (select terms (send plot :logit-terms)) terms))
             (terms (if (> num-indicators 0) 
                        (combine terms (send object :label-current-indicators))
                        terms))
             (max-length (max (mapcar #'(lambda (len) (send self :text-width len))
                                      terms)))
             )
        (send plot :draw-color 'cyan)
        
        ; (mapcar #'(lambda (pos term)  
                      ;            (send self :draw-text-up term (first pos) 
                                         ;    (-  (second pos) (- max-length 2)) 0 1)) positions terms)
        (mapcar #'(lambda (pos term)  
                    (send self :draw-text-up term (first pos) 
                          (second pos) 0 1)) positions terms)
        (send plot :draw-color 'black)
        max-length
        ))

    (defmeth plot :logit-terms ()
     	(let
        (
         (model (send (send object :curr-model) :set-model))
         (logit-elements (append 
                          (list (list (send object :dependent-variable)))
                                (expand-hierarchy 
                                 (list (remove  (send object :dependent-variable) 
                                                (iseq (length (send object :vars)))))))))
        
       (sort-data (set-difference (iseq (length model))
                                  (mapcar #'(lambda (lg-el) (position lg-el model :test 'equal))
                                          logit-elements)
                                  ))))
	
    
    (defmeth plot :new-plot ()
      (send self :start-buffering)
      (send self :clear-points)
      (send self :clear-lines)
      (let* (
             (num-lab (mapcar 'length (send object :level-labels)))
             (model (send (send object :curr-model) :set-model))
             (num-indicators (length (send object :label-current-indicators)))
             (num-elements-by-term  (mapcar #'(lambda (m) (reduce '* (- (select num-lab m) 1))) model))
             (num-elements-by-term (if (> num-indicators 0) (combine num-elements-by-term (repeat '1 num-indicators))
                                       num-elements-by-term))
             (coef-estimates (combine (send (send object :curr-model) :coef-estimates)))
             (coef-errors (combine (send (send object :curr-model) :coef-standard-errors)))
             ;(z (cdr (/ coef-estimates coef-errors)))
             (num-var (iseq (+ num-indicators (length model))))
             (num-var (if (send object :dependent-variable) (iseq (+ num-indicators (length (send plot :logit-terms))))
                          num-var))
             (num-elements-by-term (if (send object :dependent-variable) 
                                       (select num-elements-by-term (send plot :logit-terms))
                                       num-elements-by-term))
             (x (+ 2 (combine (mapcar #'(lambda (v y) 
                                                  (repeat v y)) 
                                              num-var num-elements-by-term))))
             (original-pred-names (cdr (combine "Const" (send (send object :curr-model) :predictor-names))))
             ;(x (if (send object :dependent-variable) (combine (select x (send plot :logit-terms))) (+ 2 (combine x))))
             (z (if (send object :dependent-variable) (select (cdr (combine coef-estimates)) 
                                                             (send plot :logit-terms))
                          (cdr (combine coef-estimates))))
             (original-pred-names (if (send object :dependent-variable) 
                                      (select original-pred-names (send plot :logit-terms))
                                      original-pred-names))
             ;(pred-names (cdr (combine "Const" (send object :parametter-interpretation))))
             )
        
        (send self :add-points 
              x
              ;z
              z
              :point-labels original-pred-names  
              :symbol 'x
              :color 'blue)
        
        (send self :adjust-to-data)
        (send plot :range '0 1 (+ 3 num-var))
        (send plot :range '1 (min (- (min z) (* 1.96 coef-errors))) (max (+ (* 1.96 coef-errors) (max z))))
        (setf min-range (min (send plot :range '0)))
        (setf max-range (max (send plot :range '0)))
        (send plot :add-lines (list (list min-range max-range) 
                                    (list 0 0)) :color 'orange :type 'dashed)
        #|(send plot :add-lines (list  (list min-range max-range) 
                                     (list 1.96 1.96)) :color 'orange :type 'dashed)
        (send plot :add-lines (list  (list min-range max-range) 
                                     (list -1.96 -1.96)) :color 'orange :type 'dashed)|#
        
        (send plot :x-axis t t 0)
	(let* ((coef-standard-errors
         (if (send object :dependent-variable)
                   (select 
                    (cdr (combine (send (send object :curr-model) :coef-standard-errors)))
                    (send plot :logit-terms))
             (cdr (combine (send (send object :curr-model) :coef-standard-errors)))))
           )
      (print coef-standard-errors)
      (send plot :show-window)
     	(print (* 1.96 coef-standard-errors))
      (symbol :plot plot :type 'vertical-line-with-ticks-when-selected 
             	:heigths (* 4 coef-standard-errors)))
        (if (send object :hierarchical-model?) (send self :showing-labels nil) (send self :showing-labels t))
        (send self :redraw)
        (send self :buffer-to-screen)
      ))

   (defmeth plot :compute-content-rect ()
      (setf ct-rect (send self :content-rect))
      (setf max-label (send self :print-var-labels))
      (send self :content-rect
            (first ct-rect) 
            (second ct-rect) 
            (third ct-rect)
            (- (fourth ct-rect) max-label)))
    
    (defmeth plot :redraw ()
      (send self :start-buffering)
      (let* (
             (pred-names (send object :parametter-interpretation))
             (pred-names (if (send object :dependent-variable) 
                             (select pred-names (send plot :logit-terms))
                             pred-names))
             (numerators (mapcar #'(lambda (pred) (first (combine pred)))
                                pred-names))
             (denominators (mapcar #'(lambda (pred) (second (combine pred)))
                                    pred-names))
             (end-part (mapcar #'(lambda (pred) (third (combine pred)))
                               pred-names))
             ); note that here it is used a call to the method instead of using the variable pred. This corrects a bug.      
      (setf half-range (/ (abs (apply '- (send self :range '0))) 2))
      (call-next-method)
      (send self :print-var-labels)
      (when  (and (send self :selection) 
                  (send object :hierarchical-model?)
                  (send self :slot-value 'print-interpretation-labels)
                  )
               (mapcar #'(lambda (point)
                           (let ((dif-width (- (send self :text-width (select numerators point))
                                               (send self :text-width (select denominators point))))
                                 (max-width (max (mapcar #'(lambda (w) 
                                                             (send self :text-width (select w point)))
                                                         (list numerators denominators))))
                                 (max-car (max (mapcar #'(lambda (w) 
                                                             (length (select w point)))
                                                         (list numerators denominators))))
                                 (right-side-p (>  (send self :point-coordinate '0 point) half-range))
                                 )
                             (setf pos (send self :real-to-canvas 
                                             (send self :point-coordinate '0 point)
                                             (send self :point-coordinate '1 point)))
                             (setf (select pos 0) (if right-side-p 
                                                      (- (select pos 0)  
                                                         (+ 7 (send self :text-width (select end-part point)))
                                                         )
                                                      (+ 7 (select pos 0))
                                                      ))
                              (setf (select pos 1) (- (select pos 1) (round (* 1.5 (send plot :text-ascent)))))
                             (send self :draw-text (select numerators point)
                                         (first pos)
                                         (second pos)
                                         (if right-side-p
                                             2 0)
                                         1)
                                   (send self :draw-text (apply 'strcat (repeat "_" max-car))
                                         (first pos)
                                         (round (/ (+ (second pos) (+ (second pos) (* 1 (send plot :text-ascent)))) 2))
                                         (if right-side-p
                                             2 0) 1)
                                   (send self :draw-text (select denominators point)
                                         (if right-side-p
                                             (- (first pos) dif-width)
                                             (first pos))
                                         (+ (second pos) (* 2 (send plot :text-ascent)))
                                         (if right-side-p
                                             2 0) 1)
                                   (send self :draw-text (select end-part point)
                                         (if right-side-p
                                             (+ (first pos) (send self :text-width (select end-part point)))
                                             (+ (first pos) max-width))
                                         (round (/ (+ (second pos) (+ (second pos) (* 2 (send plot :text-ascent)))) 2))
                                         (if right-side-p
                                             2 0) 1)
                                   ))
                           (send self :selection))))
      (send self :exp-right-labels)
      (send plot :right-ticks)
      (send self :buffer-to-screen)
      
      )

    (defmeth plot :unselect-all-points ()
      (call-next-method)
      (send self :redraw)
      )

 

    (let* ((coef-standard-errors
         (if (send object :dependent-variable)
                   (select 
                    (cdr (combine (send (send object :curr-model) :coef-standard-errors)))
                    (send plot :logit-terms))
             (cdr (combine (send (send object :curr-model) :coef-standard-errors)))))
           )
      (print coef-standard-errors)
      (send plot :show-window)
     	(print (* 1.96 coef-standard-errors))
      (symbol :plot plot :type 'vertical-line-with-ticks-when-selected 
             	:heigths (* 4 coef-standard-errors)))
      plot
      ))
  
(defmeth vista-loglinear-proto :hierarchical-model? ()
  (let* ((max-model (expand-hierarchy (list (iseq (length (send self :vars))))))
         (any-indicator? (set-difference 
                                         (select (send self :terms) (send self :current-num-adjusted-model))
                          (iseq (length max-model))
                                         :test 'equal)))
                         
    (cond ((not any-indicator?)
           (setf model 
                (select max-model (select (send self :terms) (send self :current-num-adjusted-model))))
           (equal model (expand-hierarchy model)))
      (any-indicator?
       nil))))


(defmeth vista-loglinear-proto :current-set-model ()
  (let* ((curr-model (send self :curr-model))
         (set-model (send curr-model :set-model))
         (set-model (mapcar #'(lambda (v)
               (when (> (length v) 1) 
                     (setf v
                           (select v 
                              (rank 
                              (mapcar #'(lambda (p) 
                               (position p  (send self :order-of-variables) :test 'equal))
                             v)))))
                      v
                     )
                  set-model))
         (terms (send self :list-terms))
         (terms-vars (mapcar #'(lambda (st-mod) (select terms st-mod))
             set-model)))
    
    (mapcar #'(lambda (x) (apply 'strcat (car x)
                                 (mapcar #'(lambda (y) 
                                             (strcat "|" y )) 
                                         (cdr x))))
            terms-vars)

    ))


#|(defmeth vista-loglinear-proto :parametter-interpretation ()
  (let* ((list-vars (send self :vars))
         (list-labels (send self :level-labels))
         (model-list (send (send self :curr-model) :set-model))
         (model-list-vars (mapcar #'(lambda (var-num)
                                      (select list-vars var-num))
                                  model-list))
         (res (combine (mapcar #'(lambda (variable-index)
                (mapcar #'(lambda (ct-cat)   
                            (strcat 
                             (strcat "("
                                     (send self :print-interp ct-cat 
                                                  (send self :reference-categories variable-index))
                                     ")")
                             (if (or
                                  (= (length variable-index) (length list-vars))
                                  (not (send self :create-constant-part variable-index model-list)))
                                 (first (introduce-symbol 
                                                    (send self :create-constant-part variable-index model-list)))
                                 (strcat "|" 
                                            (first (introduce-symbol 
                                                    (send self :create-constant-part variable-index model-list))))
                            )))
                        (send self :content-categories variable-index)))
                     model-list))))
    res)
  )|#

(defmeth vista-loglinear-proto :parametter-interpretation ()
   (when (not (send self :order-of-variables))
         (send self :order-of-variables (iseq (length (send self :vars)))))
  (let* ((list-vars (send self :vars))
         (list-labels (mapcar #'(lambda (lab) (combine (first lab) 
                                                       (sort-data (rest lab)))) 
                              (send self :level-labels))); was(send self :level-labels))
   ; (list-labels (select list-labels (send self :order-of-variables)))
    (model-list (send (send self :curr-model) :set-model)) 
  
         (res (apply 'append 
                     (mapcar #'(lambda (variable-index)
                              (when (> (length variable-index) 1) 
                                  (setf variable-index
                                        (select variable-index 
                                            (rank (mapcar #'(lambda (p) 
                                                        (position p (send self :order-of-variables) :test 'equal))
                                                    variable-index))))
                                     )

                         (mapcar #'(lambda (ct-cat)
                                    
                                     
                            (list         
                                     (send self :print-interp ct-cat 
                                                  (send self :reference-categories variable-index))
                             (if (or
                                  (= (length variable-index) (length list-vars))
                                  (not (send self :create-constant-part variable-index model-list)))
                                 (first (introduce-symbol 
                                                    (send self :create-constant-part variable-index model-list)))
                                 (strcat "|" 
                                            (first (introduce-symbol 
                                                    (send self :create-constant-part variable-index model-list))))
                            )))
                        (send self :content-categories variable-index)))
                     model-list))))
    res)
  )

;Esta función calcula si un item que puede ser una lista forma parte de la lista. 
;Podría convertirse en una función temporal dentro del siguiente método.
(defun diff-with-items-of-list (item list)
    "Args :item is a list and list is a list of lists. This function outputs the difference of the items in the list respect to the item when item is a member of a item of the list"
    (let ((item item)
          (list list)
          (diff (mapcar #'(lambda (item-list)
                      (set-difference item-list item)
                      )
                        list)))
      (mapcar #'(lambda (difs item-list) 
                  (if (and
                       difs
                       (= (length difs) (- (length item-list) (length item)  )))
                      difs
                      nil))
              diff list)))

(defmeth vista-loglinear-proto :create-constant-part (variable-vars &optional model-list)
  (let* ((variable-vars variable-vars)
         (model-list model-list)
         (list-vars (send self :vars))
         (num-vars (length list-vars))
         (list-labels (send self :level-labels));was (mapcar #'sort-data (send self :level-labels)))
         ;(included-vars (sort-data (set-difference (iseq num-vars) variable-vars)))
         (included-vars (remove-duplicates (remove 'nil (combine (diff-with-items-of-list variable-vars model-list)))))
         (pos-variable-vars 
          (mapcar #'(lambda (var)
                      (position var list-vars :test 'equal))
                  variable-vars))
         (pos-variable-constante (set-difference (iseq num-vars) pos-variable-vars ))
         (categories-constante 
          (mapcar #'(lambda (pos) 
                      (select (select list-labels pos) 0)
                      )
                  pos-variable-constante)))
    (select (reverse categories-constante) included-vars)))


(defun introduce-symbol (arg &optional (symbol "|"))
  "Arg: a list of strings. Returns a string with the symbol between the elements of the list"
  (let* (
         (arg (list arg))
         (symbol symbol))
  (mapcar #'(lambda (x) (apply 'strcat (car x)
                               (mapcar #'(lambda (y) 
                                           (strcat symbol y )) 
                                       (cdr x))))
          arg)
    ))



(defmeth vista-loglinear-proto :print-interp (content-category reference-category)
  (let* ((cont-category content-category)
         (ref-category reference-category)
         (res-ref)
         (res-cat)
         (res)
         )
    (cond 
      ((= (length cont-category) 1)
       (first (introduce-symbol (combine 
                                 (first cont-category)
                                 (first ref-category)) "/"))
       (list (first cont-category) (first ref-category))
       );aquí es el sitio donde se juntan las dos listas finales
      ((> (length cont-category) 1)
       (setf res-cat
             (introduce-symbol
              (combine
               (strcat "(" (first (introduce-symbol 
                                   (combine (first cont-category) (first ref-category))
                                   "/"))
                       ")")
               (second cont-category))))
      (setf res-ref
             (introduce-symbol
              (combine
               (strcat "(" (first (introduce-symbol 
                                   (combine (first cont-category) (first ref-category))
                                   "/"))
                       ")")
               (second ref-category))))
       (setf res-cat (combine (strcat "(" (first res-cat) ")")))
       (setf res-ref (combine (strcat "(" (first res-ref) ")")))
       (setf cont-category (remove 'nil (combine res-cat (cdr (cdr cont-category)))))
       (setf ref-category (remove 'nil (combine res-ref (cdr (cdr ref-category)))))
       (send self :print-interp cont-category ref-category)
       ))
    ))

(defmeth vista-loglinear-proto :reference-categories (variable-index)
  "Args: Positions of variables in the list of variables. Returns the reference
categories por that variables or interaction term."
  (let ((list-labels (send self :level-labels)); was (mapcar #'sort-data (send self :level-labels)))
        (variable-index variable-index))
    (mapcar #'(lambda (vars) 
                (first (select list-labels vars)))
            variable-index)))

(defmeth vista-loglinear-proto :content-categories (variable-index)
  "Args: Positions of variables in the list of variables. Returns the non-reference
categories por that variables or interaction term."
  (let* ((list-labels (mapcar 'cdr (select (send self :level-labels) variable-index))); was (mapcar #'sort-data (send 
         (labels-num (all-profile-list (mapcar #'length list-labels)))
         (variable-index variable-index)
         (select-labels-num 
          (select labels-num
                  (which (mapcar #'(lambda (lab) 
                                     (= (length lab) (length variable-index)))
                                 labels-num))))
         )
    (mapcar #'(lambda (sel-lab-num)
                (mapcar #'(lambda (list-lab lab-num)
                            (select list-lab lab-num))
                        list-labels sel-lab-num))
                select-labels-num)
    ))



    

;(setf a (send current-model :parametters-plot))